package edu.hit.irlab.coref.resolve.algorithm;

import java.util.ArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.hit.irlab.coref.CRConfigProperties;
import edu.hit.irlab.coref.PairInstance;
import edu.hit.irlab.coref.mentionfinder.Mention;
import edu.hit.irlab.coref.resolve.Entity;
import edu.hit.irlab.coref.resolve.Resolver;

/**
 * The <i>BestFirst</i> algorithm is to select the best
 * <i>Mention</i> , which satisfy particular conditions,
 * as the right Antecedent for the <i>Mention</i>
 * @author chuter
 *
 */
public class BestFirst extends ResolveAlgorithm {
	
	public BestFirst(Resolver[] resolvers) {
		super(resolvers);
	}

	@Override
	public ArrayList<Entity> resolve(Mention[] mentions) {
		ArrayList<Entity> clusters = new ArrayList<Entity>();
        int entity_id = 0;
        for (int i = 0; i < mentions.length; i++) {
        	int j = resolveSingle(mentions, i);
        	if (j >= 0 && j < mentions.length) {
            	//the two mentions refer to the same entity
                clusters.add(new Entity(
                		String.valueOf(entity_id),
                		new Mention[]{mentions[i], mentions[j]}));
            } else {
            	//the entity with only one Mention
                clusters.add(new Entity(
                		String.valueOf(entity_id),
                		new Mention[]{mentions[i]}));
            }
        	entity_id++;
        }
        
        return clusters;
	}

	@Override
	public int resolveSingle(Mention[] mentions, int ana) {
		Mention m_i = mentions[ana];
		
		double best_score = -1.0;
		int max_m_id = -1;
		for (int base_j = ana-1; base_j >= 0; base_j -= CHUNK_SIZE) {
			final int low_j;
	        if (base_j < CHUNK_SIZE)
	        	low_j = 0;
	        else
	        	low_j = base_j-CHUNK_SIZE+1;
	        for (int j = base_j; j >= low_j; j--) {
	        	Mention m_j = mentions[j];
	        	if (m_i.overlapsWith(m_j) || m_i.embeds(m_j))
	        		continue;
	        	PairInstance inst = new PairInstance(m_i, m_j);
	        	double corf_value = maxScore(inst);
	        	if (corf_value > best_score) {
	        		best_score = corf_value;
	        		max_m_id = j;
	        	}
	        }
	        if (best_score >= this._threshold)
        		return max_m_id;
		}
		
		return -1;
	}
	
}
